package com.financing.wap.service.impl;

import com.financing.wap.common.CommonConstantUtil;
import com.financing.wap.common.CommonConstantUtil.CommonStatus;
import com.financing.wap.dao.ICommonDao;
import com.financing.wap.dto.DstArticleCategoriesDTO;
import com.financing.wap.dto.DstArticleDTO;
import com.financing.wap.dto.DstUserArticleDTO;
import com.financing.wap.dto.DstUserSettingDTO;
import com.financing.wap.dto.DstUserVisitLogDTO;
import com.financing.wap.service.ICommonService;
import com.financing.wap.service.IDstArticleService;
import com.financing.wap.service.IDstUserArticleService;
import com.financing.wap.util.*;
import com.financing.wap.vo.ArticleInfoVO;
import com.financing.wap.vo.DstUserCountInfoVO;
import com.financing.wap.vo.DstUserVisitLogVO;
import com.financing.wap.vo.admin.AdminArticleInfoVO;
import com.financing.wap.vo.admin.AdminUserInfoVO;
import com.financing.wap.vo.admin.AdminUserInvitationVO;
import com.financing.wap.vo.admin.AdminUserVO;
import com.google.common.base.Splitter;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * 
*
 */
@Service("commonService")
@Transactional(rollbackFor=Exception.class)
public class CommonServiceImpl extends BaseServiceImpl implements ICommonService {

	@Autowired
	private ICommonDao commonDao;
    @Autowired
    private IDstArticleService dstArticleService;
    @Autowired
    private IDstUserArticleService dstUserArticleService;

	private String fileBaseDir=PropertiesUtils.getValue("fileBaseDir");
	
	private String ossBaseDir=PropertiesUtils.getValue("ossBaseDir");

    private ExecutorService es = Executors.newSingleThreadExecutor();

    private ExecutorService all = Executors.newFixedThreadPool(30);

	@Override
	public List<DstUserCountInfoVO> querySendDataList(DstUserSettingDTO dto)
			throws SQLException {
		return commonDao.querySendDataList(dto);
	}

	@Override
	public List<DstUserCountInfoVO> querySendHotArticleList(
			DstUserSettingDTO dto) throws SQLException {
		return commonDao.querySendHotArticleList(dto);
	}

	@Override
	public List<DstUserCountInfoVO> sendSummaryReminderList(
			DstUserSettingDTO dto) throws SQLException {
		return commonDao.sendSummaryReminderList(dto);
	}

	@Override
	public DstUserCountInfoVO visitDateLog(String openid) throws SQLException {
		return commonDao.visitDateLog(openid);
	}

	@Override
	public List<ArticleInfoVO> visitArticleInfo(String openid)
			throws SQLException {
		return commonDao.visitArticleInfo(openid);
	}

	@Override
	public ArticleInfoVO visitArticleInfoGetFisrt(String openid)
			throws SQLException {
		 List<ArticleInfoVO> visitArticleInfo = commonDao.visitArticleInfo(openid);
		 if(visitArticleInfo.size()>0){
			 return visitArticleInfo.get(0);
		 }
		 return null;
	}

	@Override
	public List<DstUserVisitLogVO> dstUserVisitLogList(DstUserVisitLogDTO dstUserVisitLog) {
		return commonDao.dstUserVisitLogList(dstUserVisitLog);
	}

	@Override
	public int dstUserVisitLogListCount(DstUserVisitLogDTO dstUserVisitLog) {
		return commonDao.dstUserVisitLogListCount(dstUserVisitLog);
	}

	@Override
	public void addVisitArticleLog(DstArticleDTO dto) throws SQLException {
		commonDao.addVisitArticleLog(dto);
	}

	@Override
	public List<DstArticleDTO> myAllArticleInfo(DstArticleDTO dstArticle)
			throws SQLException {
		return commonDao.myAllArticleInfo(dstArticle);
	}

	@Override
	public int myAllArticleInfoCount(DstArticleDTO dstArticle)
			throws SQLException {
		return commonDao.myAllArticleInfoCount(dstArticle);
	}

	@Override
	public int adminArticleInfoCount(AdminArticleInfoVO dstArticle) {
		return commonDao.adminArticleInfoCount(dstArticle);
	}

	@Override
	public List<AdminArticleInfoVO> adminAllArticleInfo(AdminArticleInfoVO dstArticle) {
		return commonDao.adminAllArticleInfo(dstArticle);
	}
	
	@Override
	public int allArticleTypeInfoCount(DstArticleCategoriesDTO dto) {
		return commonDao.allArticleTypeInfoCount(dto);
	}

	@Override
	public List<DstArticleCategoriesDTO> allArticleTypeInfo(DstArticleCategoriesDTO dto) {
		return commonDao.allArticleTypeInfo(dto);
	}

	@Override
	public DstArticleDTO  createArticle(Map<String,String> map)  {
        String content = map.get("content");
        final String fromUserName = map.containsKey("fromUserName")?map.get("fromUserName"):"";
        String userName = map.get("userName");
        String articleStatus = map.get("articleStatus");
        String categories = map.containsKey("categories")?map.get("categories"):"";
        String resource = map.containsKey("resource")?map.get("resource"):"";

        final long time=System.currentTimeMillis();
        //TODO 文章解析时间过长 日志测试结果
        String result = RequstUtil.doRequest(content);
        logger.info("request --article  content:"+(System.currentTimeMillis()-time)/1000);
        String titleRegex="var msg_title = \"(.*?)\"";
        String msgUrlRegex="var cdn_url_235_1 = \"(.*?)\"";
        String lastMsgUrlRegex="var msg_cdn_url = \"(.*?)\"";
        String msgDescRegex="var msg_desc = \"(.*?)\"";
        String contetRegex="(<div class=\"rich_media_content \" id=\"js_content\">[\\s\\S]*?)<script";
        
        //企业微信单独处理
		if (map.get("wxpathurl").contains("open.work.weixin.qq")) {
			titleRegex = "title: '(.*?)',";
			msgUrlRegex = "shareLogo: '(.*?)',";
			msgDescRegex = "abstract : '(.*?)',";
			contetRegex = "(<div class=\"notice_main\" id=\"notice_main\">[\\s\\S]*?)<div class=\"notice_footer\">";
		}
        
        final String title = StringUtil.fecth(result, titleRegex, 1);
        final String dstArticleCode= UUID.randomUUID().toString().replace("-", "");
        final String articleUrl=MessageFormat.format(CommonStatus.articleDetailPage, dstArticleCode,fromUserName);
        String imageThumbnail = StringUtil.fecth(result, msgUrlRegex, 1);
        if(StringUtil.isNullOrEmptyStr(imageThumbnail))
        	imageThumbnail = StringUtil.fecth(result, lastMsgUrlRegex, 1);
        map.put("imageThumbnail", imageThumbnail);
        //下载图片  替换  非企业微信需要下载  分享图
        if (!map.get("wxpathurl").contains("open.work.weixin.qq")) {
        	imageThumbnail=downThumbnail(imageThumbnail);
        }

        final String description = StringUtil.fecth(result, msgDescRegex, 1);

        String contentResult = StringUtil.fecth(result, contetRegex, 1);

        final String c=contentResult;
        // 文章入库
        final DstArticleDTO dstArticle = new DstArticleDTO();
        dstArticle.setTitle(title);
        dstArticle.setResource(resource);
        dstArticle.setWxPath(content);
        dstArticle.setDstArticleCode(dstArticleCode);
        dstArticle.setUrl(articleUrl);
        dstArticle.setArticleUploads(userName);
        dstArticle.setArticleStatus(articleStatus);
        if(StringUtils.isNotBlank(categories)){
            dstArticle.setCategories(categories);
        }
        //备注 图片
        dstArticle.setThumbnail(imageThumbnail);
        dstArticle.setDescription(description);
        DTOdateSetUtil.setCreateInfo(dstArticle);
        DTOdateSetUtil.setUpdateInfo(dstArticle);
        dstArticle.setDeleteTag(CommonConstantUtil.CommonStatus.DELETE_TAG_NORMAL);
        
        // 用户绑定文章
        final DstUserArticleDTO dstUserArticle = new DstUserArticleDTO();
        dstUserArticle.setUserOpenid(fromUserName);
        dstUserArticle.setRelArticleId(dstArticle.getId());
        dstUserArticle.setDstArticleCode(dstArticleCode);
        DTOdateSetUtil.setCreateInfo(dstUserArticle);
        DTOdateSetUtil.setUpdateInfo(dstUserArticle);
        dstUserArticle
                .setDeleteTag(CommonConstantUtil.CommonStatus.DELETE_TAG_NORMAL);
        
        es.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    // 处理为包含P标签的 
                    String parseResult=parsePTag(c);
                    // 核心内容
                    dstArticle.setContent(parseResult);
                    dstUserArticle.setDstArticleContent(parseResult);
                    dstArticleService.insert(dstArticle);
                    //有用户openid生成用户专属文章
                    if(StringUtils.isNotBlank(fromUserName)){
                    	dstUserArticle.setTitle(dstArticle.getTitle());
                    	dstUserArticle.setThumbnail(dstArticle.getThumbnail());
                    	dstUserArticle.setDescription(dstArticle.getDescription());
                    	dstUserArticleService.insert(dstUserArticle);
                    }
                } catch (SQLException error) {
                    logger.error("insert userAritcle :",error);
                }
            }
        });

        return dstArticle;
	}

    @Override
    public List<String> dstUserVisitLogGroupDate(DstUserVisitLogDTO dstUserVisitLog) {
        return commonDao.dstUserVisitLogGroupDate(dstUserVisitLog);
    }

    @Override
    public Map<String,String> queryOperationStatisticsForAll(Map<String, String> papMap) {
        return commonDao.queryOperationStatisticsForAll(papMap);
    }

    @Override
    public List<Map<String, String>> queryOperationStatisticsForDailyDischarge(Map<String, String> papMap) {
        return commonDao.queryOperationStatisticsForDailyDischarge(papMap);
    }

    @Override
    public List<Map<String, String>> queryOperationStatisticsForDailyDischargeUser(Map<String, String> papMap) {
        return commonDao.queryOperationStatisticsForDailyDischargeUser(papMap);
    }

    @Override
    public List<Map<String, String>> queryOperationStatisticsForArticleTrend(Map<String, String> papMap) {
        return commonDao.queryOperationStatisticsForArticleTrend(papMap);
    }

    @Override
    public List<Map<String, String>> queryOperationStatisticsForArticleType(Map<String, String> papMap) {
        return commonDao.queryOperationStatisticsForArticleType(papMap);
    }

    @Override
    public List<Map<String, String>> listDstUserVisitLogShare(Map<String, String> papMap) {
        return commonDao.listDstUserVisitLogShare(papMap);
    }

    @Override
    public List<Map<String, Object>> listDstUserVisitLogShareIcon(Map<String, String> papMap) {
        return commonDao.listDstUserVisitLogShareIcon(papMap);
    }

    @Override
    public List<Map<String, Object>> listDstUserVisitLogIcon(Map<String, String> papMap) {
        return commonDao.listDstUserVisitLogIcon(papMap);
    }

    @Override
    public void addUserWeeklyTypeZh(Map<String, String> papMap) {
         commonDao.addUserWeeklyTypeZh(papMap);
    }

    @Override
    public void articleRealTimePush(Map<String, String> map) {
        commonDao.articleRealTimePush(map);
    }

    @Override
    public int queryUserInfoListCount(AdminUserVO adminUserVO) {
        return commonDao.queryUserInfoListCount(adminUserVO);
    }

    @Override
    public List<AdminUserVO> queryUserInfoList(AdminUserVO adminUserVO) {
        return commonDao.queryUserInfoList(adminUserVO);
    }

    @Override
    public AdminUserInfoVO queryUserInfoDetailed(String openid) {
        return commonDao.queryUserInfoDetailed(openid);
    }

    @Override
    public List<AdminUserInvitationVO> adminUserInvitationList(String openid) {
        return commonDao.adminUserInvitationList(openid);
    }

    /**
     * 下载图片 返回oss地址
     * @param imageThumbnail
     * @return
     */
    private String downThumbnail(String imageThumbnail) {
        String path = imageThumbnail;
        //目录
        StringBuffer fileFull = new StringBuffer();
        fileFull.append(ossBaseDir)
                .append("/")
                .append(StringUtil.dateNowStr("yyyyMMdd"));
        //文件全路径
        final StringBuffer fileFullPath = new StringBuffer(fileFull.toString());
        String randomName = "_"+UUID.randomUUID().toString()+""+new Random().nextInt(6);
        try {
            //后缀
            fileFullPath.append("/").append(randomName).append(".jpg").toString();
            AliyunOssUtil.writeFile(RequstUtil.doRequestStreamByWxImage(imageThumbnail), fileFullPath.toString());
            path = CommonConstantUtil.OSS_PATH+fileFullPath;
        } catch (Exception e) {
            logger.error("imageThumbnail:"+imageThumbnail);
            logger.error("upload thumbnail error ",e);
            try {
                AliyunOssUtil.writeFile(RequstUtil.doRequestStreamByWxImage(imageThumbnail), fileFullPath.toString());
                path = CommonConstantUtil.OSS_PATH+fileFullPath;
            } catch (Exception e1) {
                logger.error("retry imageThumbnail:"+imageThumbnail);
                logger.error("retry upload thumbnail error ",e1);
            }
        }
        return path;
    }

    
    /**
     * 下载图片 到服务器   弃用
     * @param imageThumbnail
     * @return
     */
    private String downThumbnailTolocal(String imageThumbnail) {
        String path = imageThumbnail;
        //目录
        StringBuffer fileFull = new StringBuffer();
        fileFull.append(ossBaseDir)
                .append("/")
                .append(StringUtil.dateNowStr("yyyyMMdd"));
        //文件全路径
        final StringBuffer fileFullPath = new StringBuffer(fileFull.toString());
        String randomName = "_"+UUID.randomUUID().toString()+""+new Random().nextInt(6);
        try {
            //后缀
            fileFullPath.append("/").append(randomName).append(".jpg").toString();
            InputStream doRequestStreamByWxImage = RequstUtil.doRequestStreamByWxImage(imageThumbnail);
            if(doRequestStreamByWxImage==null){
            	doRequestStreamByWxImage = RequstUtil.doRequestStreamByWxImage(imageThumbnail);
            }
            //目录
			File dir = new File(fileBaseDir + fileFull.toString());
			if (!dir.exists()) {
				dir.mkdirs();
			}
			//上传 文件
			File fileTmp = new File(fileBaseDir + fileFullPath.toString());
			if (!fileTmp.exists()) {
				fileTmp.createNewFile();
				logger.info("create new file !");
			}
			IOUtils.copy(doRequestStreamByWxImage, new FileOutputStream(fileTmp));
            path = CommonConstantUtil.LOCAL_PATH+fileFullPath;
        } catch (Exception e) {
            logger.error("downThumbnailTolocal:"+imageThumbnail);
            logger.error("upload downThumbnailTolocal error ",e);
        }
        return path;
    }

    /***
     * 处理P标签
     * @param contentResult
     * @return
     */
    private String parsePTag(String contentResult) {
        if(StringUtil.isNullOrEmptyStr(contentResult))return "";
        
		long date = System.currentTimeMillis();
        Document parse = Jsoup.parse(contentResult);
        Element c = parse.getElementById("js_content");
        if(c==null){//企业微信
        	c=parse.getElementById("notice_main");
            Elements elementsByTag = c.getElementsByTag("img");
        	 for (final Element element : elementsByTag) {
                 String dataSrc=element.attr("data-src");
                 element.attr("src",dataSrc);
        	 }
            //TODO 测试环境 处理 过滤 特殊字符
            String res= EmojiFilterUtil.filterEmoji(c.html());
            return res;
        }

        //TODO 页面加载慢 暂时不处理视频   直接注释
          //处理所有的iframe src  
        Elements iframes = c.getElementsByTag("iframe");
        for (Element iframe : iframes) {
            try {
				String dataSrc=iframe.attr("data-src");
				if(StringUtil.isNullOrEmptyStr(dataSrc))continue ;
				String vid= getParam(dataSrc, "vid");
				if(dataSrc.contains("mp.weixin.qq.com")){
				    iframe.attr("src","http://mp.weixin.qq.com/mp/readtemplate?t=pages/video_player_tmpl&auto=0&vid="+vid);
				}else if(dataSrc.contains("v.qq.com")){
				    iframe.attr("src","http://v.qq.com/iframe/player.html?vid="+vid);
				}
			} catch (Exception e) {
				logger.error("parse vidio error",e);
			}
        }

        //是否需要过滤
        Elements elementsByTag = c.getElementsByTag("img");
        //目录
        final StringBuffer fileFull = new StringBuffer();
        fileFull.append(ossBaseDir)
                .append("/")
                .append(StringUtil.dateNowStr("yyyyMMdd"));
        List<Future> future=new ArrayList<Future>();
        //防盗链处理
        for (final Element element : elementsByTag) {
            final String dataSrc=element.attr("data-src");
            if(!StringUtil.isNullOrEmptyStr(dataSrc)){
                future.add(all.submit(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            //文件全路径
                            final StringBuffer fileFullPath = new StringBuffer(fileFull.toString());
                            String randomName = "_"+UUID.randomUUID().toString()+""+new Random().nextInt(6);
                            //后缀
                            fileFullPath.append("/")
                                    .append(randomName)
                                    .append(".jpg").toString();
                            new Thread(new Runnable() {
                                public void run() {
                                    try {
                                        AliyunOssUtil.writeFile(RequstUtil.doRequestStreamByWxImage(dataSrc), fileFullPath.toString());
                                    } catch (Exception e) {
                                        logger.info("dataSrc:"+dataSrc);
                                        logger.error("down image to oss:",e);
                                        try {
                                            AliyunOssUtil.writeFile(RequstUtil.doRequestStreamByWxImage(dataSrc), fileFullPath.toString());
                                        } catch (Exception e1) {
                                            logger.info("retry dataSrc:"+dataSrc);
                                            logger.error("retry down image to oss:",e1);
                                        }
                                    }
                                }
                            }).start();
                            String path=CommonConstantUtil.OSS_PATH+fileFullPath;
                            element.attr("data-src",path);
                            element.attr("src",path);
                        } catch (Exception e) {
                            logger.error("future.get",e);
                        }
                    }
                }));
            }
        }
        for (Future future2 : future) {
            try {
                if(future2!=null)
                    future2.get();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        long currentTimeMillis = System.currentTimeMillis();
        logger.info("处理文章图片结束..."+(currentTimeMillis-date)/1000);
        //TODO 测试环境 处理 过滤 特殊字符
        String res= EmojiFilterUtil.filterEmoji(c.html());
        logger.info("处理 过滤 特殊字符..."+(currentTimeMillis-date)/1000);
        //TODO 后续如果需要下载 删除所有背景图片  
        return res.replaceAll("background-image:\\s*?url\\((&quot;|')(.*?)(&quot;|')\\);", "");
    }
    public static String getParam(String url, String name) {
        String params = url.substring(url.indexOf("?") + 1, url.length());
        Map<String, String> split = Splitter.on("&").withKeyValueSeparator("=").split(params);
        return split.get(name);
    }
    public static void main(String[] args) {
	        final long time=System.currentTimeMillis();
	        //TODO 文章解析时间过长 日志测试结果
//	        String result = RequstUtil.doRequest("https://open.work.weixin.qq.com/wwopen/mpnews?mixuin=r-2MCgAABwCB3Rv2AAAUAA&mfid=WW0307-iXAZQgAABwDZQaa3QGF36wNynQ535&idx=0&sn=7385e089e8d43f9ed4b8dd58f6ea7ed9&from=timeline&isappinstalled=0");
//	        String	 titleRegex="title: '(.*?)',";
//	        String    msgUrlRegex="shareLogo: '(.*?)',";
//	        String     msgDescRegex="abstract : '(.*?)',";
//	        String   contetRegex="(<div class=\"notice_main\" id=\"notice_main\">[\\s\\S]*?)<div class=\"notice_footer\">";
	        
	        String result=RequstUtil.doRequest("https://mp.weixin.qq.com/s/7LoN9_fDxMVQxd9xOLBOoA");
	        String titleRegex="var msg_title = \"(.*?)\"";
	        String msgUrlRegex="var cdn_url_235_1 = \"(.*?)\"";
	        String lastMsgUrlRegex="var msg_cdn_url = \"(.*?)\"";
	        String msgDescRegex="var msg_desc = \"(.*?)\"";
	        String contetRegex="(<div class=\"rich_media_content \" id=\"js_content\">[\\s\\S]*?)<script";
	        
	        
	        
	        final String title = StringUtil.fecth(result, titleRegex, 1);
	        final String dstArticleCode= UUID.randomUUID().toString().replace("-", "");
	        String imageThumbnail = StringUtil.fecth(result, msgUrlRegex, 1);
	        	
	        final String description = StringUtil.fecth(result, msgDescRegex, 1);

	        String contentResult = StringUtil.fecth(result, contetRegex, 1);
	
	        
	        final String c=contentResult;
		System.out.println(title);
		System.out.println(dstArticleCode);
		System.out.println(imageThumbnail);
		System.out.println(description);
		System.out.println(contentResult);
//		List<String> fecthAll = StringUtil.fecthAll(c.html(), "background-image:\\s*?url\\((&quot;|')(.*?)(&quot;|')\\);", 2);
//		for (int i = 0; i < fecthAll.size(); i++) {
//			System.out.println(fecthAll.get(i));
//		}
//        System.out.println(getParam("https://v.qq.com/iframe/preview.html?width=500&height=375&auto=0&vid=d0862se7315", "vid"));
    	
//        new CommonServiceImpl().downThumbnailTolocal("http://p.qpic.cn/pic_wework/3179068750/14120a0422d35a17419af7a5cd406a77b27a0a386fcdb3bc/1280");
    }

}
